#include "fv_inc.h"
#include "wxOpenGL.h"
#include "wxMainWindow.h"
#include "ModelControler.h"
#include "ViewManager.h"
#include "Log.h"
#include "fv_txt_utls.h"
#include <wx/wx.h>

//#include <GL/glu.h>
//#include <GL/gl.h>

#ifdef __WXDEBUG__
#include<iostream>
#endif

namespace FemViewer {
namespace WxGUI		{

BEGIN_EVENT_TABLE(wxRenderCanvas, wxGLCanvas)
    EVT_SIZE(wxRenderCanvas::OnSize)
    EVT_PAINT(wxRenderCanvas::OnPaint)
	EVT_ERASE_BACKGROUND(wxRenderCanvas::OnEraseBackground)
	EVT_MOTION(wxRenderCanvas::OnMouseMove)
	EVT_MOUSEWHEEL(wxRenderCanvas::OnMouseWheel)
	EVT_LEFT_DOWN(wxRenderCanvas::OnLeftBtnDown)
	EVT_LEFT_UP(wxRenderCanvas::OnLeftBtnUp)
	EVT_MIDDLE_DOWN(wxRenderCanvas::OnMiddleBtnDown)
	EVT_MIDDLE_UP(wxRenderCanvas::OnMiddleBtnUp)
	EVT_RIGHT_DOWN(wxRenderCanvas::OnRightBtnDown)
	EVT_RIGHT_UP(wxRenderCanvas::OnRightBtnUp)
    //EVT_MOUSE_EVENTS(wxRenderCanvas::OnMouse)
	//EVT_CHAR(wxRenderCanvas::OnChar);
	EVT_ENTER_WINDOW(wxRenderCanvas::OnEnterWindow )
END_EVENT_TABLE()

wxRenderCanvas::wxRenderCanvas(
        ModelCtrl* pmodel,
		ViewManager* pview,
		wxMainWindow* parent,
		wxWindowID id,
		int* gl_attrib,
		const wxPoint& pos,
		const wxSize& size,
		long style,
		const wxString& name
		)
: wxGLCanvas(static_cast<wxWindow*>(parent),
             id, gl_attrib, pos, size,
		     style | wxFULL_REPAINT_ON_RESIZE, name)
, m_ptrModel(pmodel)
, m_pview(pview)
, m_ptrWnd(parent)
, m_ptrRC(NULL)
, m_bInitGL(false)
, m_ndraging(0)					  
{
	logd("Constryctor wxRendercanvas\n");
	wxASSERT( m_ptrModel );
	wxASSERT( m_pview );

	// Setup GL context
	m_ptrRC = new wxGLContext(this);
	wxASSERT( m_ptrRC );
	// Setup video card
	SetCurrent( *m_ptrRC ); // jesli zakomentuje to co ?
	FV_CHECK_ERROR_GL();
	//!!!!!!!!!!!!! Tu jest problem?
	//m_pview->InitGL( (int)size.GetWidth(), (int)size.GetHeight() );
	//m_pview->GetGraphicData().SetModel( m_ptrModel );

}

wxRenderCanvas::~wxRenderCanvas()
{
	logd("Destructor: ~wxRendercanvas\n");
	delete m_ptrRC;
}

void wxRenderCanvas::CleanUp()
{
	SetCurrent( *m_ptrRC );
	m_ptrModel->Do(ModelCtrl::CLEAR);

}

void wxRenderCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
{
	wxPaintDC dc( this );
    SetCurrent( *m_ptrRC );
    m_pview->DisplayCallback();
	SwapBuffers();
}

int wxRenderCanvas::Modifires(wxMouseEvent& event)
{
	int modiffier = 0;
	if(event.ShiftDown()) modiffier |= 0x1;
	if(event.ControlDown()) modiffier |= 0x2;
	if(event.AltDown()) modiffier |= 0x4;
	return modiffier;
}

void wxRenderCanvas::OnSize(wxSizeEvent &event)
{
	int w,h;
	wxGLCanvas::OnSize( event );
	SetCurrent();
	GetClientSize( &w, &h );
	glViewport( 0, 0, (GLsizei)w, (GLsizei)h );

	m_pview->ReshapeCallback( w, h );
	
	Refresh(false);
}

void wxRenderCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
{
    // Do nothing, to avoid flashing on MSW
	//m_VMgr.DisplayCallback();
}

void wxRenderCanvas::OnMouseMove(wxMouseEvent& event)
{
	if( m_ndraging ) {
		m_pview->MouseMotionCallback( event.GetX(), event.GetY() );
		Refresh(false);
	}
}

void wxRenderCanvas::OnLeftBtnDown(wxMouseEvent& event)
{
	int modif = Modifires( event );
	m_pview->MouseButtonCallback(0,0,modif,event.GetX(),event.GetY());
	Refresh(false);
	m_ndraging = 1;
}

void wxRenderCanvas::OnLeftBtnUp(wxMouseEvent& event)
{
	int modif = Modifires( event );
	m_pview->MouseButtonCallback(0,1,modif,event.GetX(),event.GetY());
	Refresh(false);
	m_ndraging = 0;
}

void wxRenderCanvas::OnMiddleBtnDown(wxMouseEvent& event)
{
	int modif = Modifires( event );
	m_pview->MouseButtonCallback(1,0,modif,event.GetX(),event.GetY());
	Refresh(false);
	m_ndraging = 1;
}

void wxRenderCanvas::OnMiddleBtnUp(wxMouseEvent& event)
{
	int modif = Modifires( event );
	m_pview->MouseButtonCallback( 1,1,modif,event.GetX(),event.GetY() );
	Refresh(false);
	m_ndraging = 0;
}

void wxRenderCanvas::OnRightBtnDown(wxMouseEvent& event)
{
	int modif = Modifires( event );
	m_pview->MouseButtonCallback(2,0,modif,event.GetX(),event.GetY());
	Refresh(false);
	m_ndraging = 1;
}

void wxRenderCanvas::OnRightBtnUp(wxMouseEvent& event)
{
	int modif = Modifires(event);
	m_pview->MouseButtonCallback( 2,1,modif,event.GetX(),event.GetY() );
	Refresh(false);
	m_ndraging = 0;
}

//void wxRenderCanvas::OnMouse(wxMouseEvent& event)
//{
//
//	if(event.Dragging()) {
//		m_VMgr.MouseMotionCallback(event.GetX(), event.GetY());
//	} else {
//
//		int modif = 0, button;
//		if(event.ShiftDown()) modif |= 0x1;
//		if(event.ControlDown()) modif |= 0x2;
//		if(event.AltDown()) modif |= 0x4;
//
//		if(event.ButtonUp()) {
//			button = event.GetButton();
//			m_VMgr.MouseButtonCallback(button,1,modif,event.GetX(),event.GetY());
//		} else if(event.ButtonDown()) {
//			button = event.GetButton();
//			m_VMgr.MouseButtonCallback(button,0,modif,event.GetX(),event.GetY());
//		}
//	}
//	Refresh(false);
//}

void wxRenderCanvas::OnMouseWheel(wxMouseEvent& event)
{
	int rot = event.GetWheelRotation();
	if(rot < 0) {
		m_pview->MouseButtonCallback(3,0,0,0,0);
		Refresh(false);
	} else if(rot > 0) {
		m_pview->MouseButtonCallback(4,0,0,0,0);
		Refresh(false);
	} else {
		m_pview->MouseButtonCallback(4,1,0,0,0);
		Refresh(false);
	}
}


void wxRenderCanvas::OnEnterWindow(wxMouseEvent& WXUNUSED(event))
{
	SetFocus();
}

//void wxRenderCanvas::Redraw(const std::string& title)
//{
//	m_VMgr.SetTitle(title);
//	m_VMgr.GetGraphicData().Reset();
//	m_pModel->SetGoemetry(m_VMgr.GetGraphicData().GetRootObject());
//	m_pModel->Redraw();
//}
//void wxRenderCanvas::GetViewportOffset() const
//{
//	SetCurrent(*m_glRC);
//	wxGLCanvas::GetPosition(
//}

void wxRenderCanvas::InitGL()
{
	glEnable (GL_DEPTH_TEST);
    //glDepthFunc (GL_LESS);
    glDepthFunc (GL_LEQUAL);
    //glDepthFunc (GL_EQUAL);
    //glDepthFunc (GL_NOTEQUAL);
    glClearColor (0.0, 0.0, 0.0, 1.0);
    glClearDepth(1.0);
   // glEnable(GL_CULL_FACE);
    glFrontFace(GL_CCW);
    glEnable(GL_POINT_SMOOTH);

    glEnable(GL_BLEND);
	//ViewManagerInst().InitGL();
}

}// end namespace WxGUI
}// end namespace FemViewer
